package com.nami.client.network;

import com.nami.client.network.codec.WsMessageDecoder;
import com.nami.client.network.codec.WsMessageEncoder;
import com.nami.client.network.handler.NettyClientHandler;
import com.nami.client.qos.QosReceiver;
import com.nami.client.request.LoginRequest;
import com.nami.client.request.ServerConfig;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.http.HttpClientCodec;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.websocketx.WebSocketClientProtocolConfig;
import io.netty.handler.codec.http.websocketx.WebSocketClientProtocolHandler;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.stream.ChunkedWriteHandler;
import lombok.extern.slf4j.Slf4j;

import java.net.InetSocketAddress;
import java.net.URI;

@Slf4j
public class NettyClient {

    private ServerConfig config;
    private LoginRequest loginRequest;

    public NettyClient(ServerConfig config, LoginRequest loginRequest) {
        this.config = config;
        this.loginRequest = loginRequest;
     }


    public Channel start() throws InterruptedException {
        NioEventLoopGroup nioEventLoopGroup = new NioEventLoopGroup();
        try {
            Bootstrap bootstrap = new Bootstrap();
            bootstrap.group(nioEventLoopGroup)
                .channel(NioSocketChannel.class)

//                .option(ChannelOption.SO_RCVBUF, 1024 * 1024)  // 设置接收缓冲区大小为1MB
//                .option(ChannelOption.SO_SNDBUF, 1024 * 1024)  // 设置发送缓冲区大小为1MB
                .option(ChannelOption.TCP_NODELAY, true)
//                // 允许重复使用本地地址和端口
                .option(ChannelOption.SO_REUSEADDR, true)
                .remoteAddress(new InetSocketAddress(config.getHost(), config.getPort()))
                .handler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel sc) throws Exception {
                        ChannelPipeline pipeline = sc.pipeline();
//                        pipeline.addLast("log", new LoggingHandler(LogLevel.DEBUG));
                        pipeline.addLast("http-codec", new HttpClientCodec());
                        // 对写大数据流的支持
                        pipeline.addLast("http-chunked", new ChunkedWriteHandler());
                        // 几乎在netty中的编程，都会使用到此hanler
                        pipeline.addLast("aggregator", new HttpObjectAggregator(65535));

                        WebSocketClientProtocolConfig config = WebSocketClientProtocolConfig.newBuilder()
                            .webSocketUri(URI.create("ws://localhost:30000/ws"))
//                            .subprotocol() // 如果服务器端有子协议，这里需要设置
                            .build();
                        pipeline.addLast("ws-handler", new WebSocketClientProtocolHandler(config));

                        pipeline.addLast("encoder", new WsMessageEncoder());
                        pipeline.addLast("decoder", new WsMessageDecoder());

                        pipeline.addLast(new NettyClientHandler(loginRequest));

                    }
                });
            ChannelFuture cf = bootstrap.connect().sync();
            return cf.channel();
        }  catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }


}
